import { SizeType } from '@/types'

interface SizePackage {
    size: number
    fontSize: number
    borderRadius: number
    space: number
}

const sizePackageMap = new Map<string, SizePackage>()
const toastElList: HTMLElement[] = []
export default {
    sleep(haomiao: number) {
        return new Promise<void>(resolve => {
            setTimeout(resolve, haomiao)
        })
    },
    getSizePackageByName(name: SizeType) {
        if (sizePackageMap.has(name)) {
            return sizePackageMap.get(name)!
        }
        let div = window.document.createElement('div')
        div.className = `c-round-${name} c-width-${name} c-font-size-${name} c-p-${name} c-position-fixed`
        window.document.body.appendChild(div)
        let csd = window.getComputedStyle(div)
        let sizePackage: SizePackage = {
            size: Number(csd.width.replace('px', '')),
            fontSize: Number(csd.fontSize.replace('px', '')),
            borderRadius: Number(csd.borderTopLeftRadius.replace('px', '')),
            space: Number(csd.padding.replace('px', '')),
        }
        div.remove()
        sizePackageMap.set(name, sizePackage)
        return sizePackage
    },
    getEl(target?: any): HTMLElement | undefined {
        if (!target) {
            return target
        }
        if (target instanceof Array) {
            return this.getEl(target[0])
        }
        if (target.$el) {
            return this.getEl(target.$el)
        }
        if ([3, 8].includes(target.nodeType)) {
            return this.getEl(target.nextElementSibling)
        }
        return target
    },

    getBase64FromDataUrl(dataUrl: string) {
        let base64Sign = 'base64,'
        return dataUrl.substring(
            dataUrl.indexOf(base64Sign) + base64Sign.length,
        )
    },

    //从input[type=file]获取dataUrl，注意，不是base64编码字符串
    getDataUrlFromFile(file: File) {
        return new Promise<string>(resolve => {
            let fr = new FileReader()
            fr.onload = () => {
                resolve(fr.result as string)
            }
            fr.readAsDataURL(file)
        })
    },

    getStorageSizeStr(size: number) {
        if (!size) {
            return '0B'
        }
        if (size / 1024 < 1) {
            return `${size}B`
        } else if (size / 1024 / 1024 < 1) {
            return `${(size / 1024).toFixed(2)}KB`
        } else if (size / 1024 / 1024 / 1024 < 1) {
            return `${(size / 1024 / 1024).toFixed(2)}MB`
        } else if (size / 1024 / 1024 / 1024 / 1024 < 1) {
            return `${(size / 1024 / 1024 / 1024).toFixed(2)}GB`
        } else if (size / 1024 / 1024 / 1024 / 1024 < 1) {
            return `${(size / 1024 / 1024 / 1024 / 1024).toFixed(2)}TB`
        } else if (size / 1024 / 1024 / 1024 / 1024 < 1) {
            return `${(size / 1024 / 1024 / 1024 / 1024 / 1024).toFixed(2)}PB`
        }
        return `${size}B`
    },

    getDecimalCount(num: number) {
        return (String(num).split('.')[1] ?? '')?.length
    },

    async toast(message: string) {
        let transitionDuration = 500
        let showDuration = 2000
        let div = window.document.createElement('div')
        div.style.position = 'fixed'
        div.style.top = '50%'
        div.style.left = '50%'
        div.style.transitionDuration = transitionDuration + 'ms'
        div.style.transitionProperty = 'opacity transform'
        div.style.background = 'rgba(0, 0, 0, 0.8)'
        div.style.color = 'white'
        div.className =
            'c-height-m c-p-h-m c-font-size-m c-f-v c-f-p-center c-shadow-m c-round-m'
        div.innerText = message

        toastElList.push(div)
        toastElList.forEach((a, i) => {
            let distance = toastElList.length - 1 - i
            a.style.transform = `translate(-50%, -${distance * 200 + 50}%)`
        })
        window.document.body.appendChild(div)

        let hovering = false
        div.addEventListener('mouseover', () => {
            hovering = true
            showFunc()
        })
        div.addEventListener('mouseout', () => {
            hovering = false
            hideFunc()
        })

        let showFunc = () => {
            div.style.opacity = '1'
        }

        let hideFunc = async () => {
            if (hovering) {
                return
            }
            await this.sleep(showDuration)
            if (hovering) {
                return
            }
            div.style.opacity = '0'
            await this.sleep(transitionDuration)
            if (hovering) {
                return
            }
            toastElList.splice(
                toastElList.findIndex(a => a === div),
                1,
            )
            div.remove()
        }
        showFunc()
        await hideFunc()
    },

    /**
     * 节流
     * @param func
     * @param wait 最少间隔的毫秒数
     * @returns
     */
    throttle(func: () => void, wait: number) {
        let timeout = undefined as number | undefined
        let lastRun = 0
        return function () {
            const now = Date.now()
            if (now - lastRun >= wait) {
                if (timeout) {
                    clearTimeout(timeout)
                    timeout = undefined
                }
                lastRun = now
                func()
            } else if (!timeout) {
                timeout = setTimeout(function () {
                    lastRun = Date.now()
                    timeout = undefined
                    func()
                }, wait - (now - lastRun))
            }
        }
    },

    /**
     * 防抖，间隔时间内最多只执行一次
     * @param func
     * @param wait
     * @returns
     */
    debounce(func: () => void, wait: number) {
        let timeout = undefined as number | undefined
        return function () {
            clearTimeout(timeout)
            timeout = setTimeout(() => {
                func()
            }, wait)
        }
    },
}
